package cn.yaoud.salus.oms.alarm.advice;

import cn.yaoud.salus.oms.alarm.Alerter;
import cn.yaoud.salus.oms.alarm.autoconfigure.OmsAlarmProperties;
import cn.yaoud.salus.oms.alarm.exception.ExpectedBusinessException;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.util.CollectionUtils;

import java.util.Objects;

/**
 * 异常告警
 *
 * @author 唐彪
 */
@Slf4j
@Aspect
public class NoticeExceptionAdvice {
    private Alerter alerter;
    private OmsAlarmProperties omsAlarmProperties;
    public void setAlerter(Alerter alerter) {
        this.alerter = alerter;
    }
    public void setOmsAlarmProperties(OmsAlarmProperties omsAlarmProperties) {
        this.omsAlarmProperties = omsAlarmProperties;
    }

    @Around("execution(* cn.yaoud.salus.common.sentinel.handle.GlobalBizExceptionHandler.*(..)) && " +
            "@annotation(org.springframework.web.bind.annotation.ExceptionHandler)"
    )
    public Object noticeException(ProceedingJoinPoint pjp) throws Throwable {
        Object proceed = pjp.proceed();
        Object[] args = pjp.getArgs();
        for (Object arg : args) {
            if (Objects.nonNull(arg) && arg instanceof Exception exception) {
                if (ignoreException(exception) || ignoreExpectedBusinessException(exception)) {
                    log.debug("忽略告警异常类型：{}，忽略预期异常：{}", omsAlarmProperties.getIgnoreExceptions(),
                            omsAlarmProperties.getIgnoreExpectedBusinessException());
                    return proceed;
                } else {
                    alerter.report(exception);
                }
            }
        }
        return proceed;
    }


    /**
     * 判断是否为配置的忽略告警异常
     *
     * @param exception 发生的异常
     * @return true忽略告警，false告警
     */
    private boolean ignoreException(Exception exception) {
        return !CollectionUtils.isEmpty(omsAlarmProperties.getIgnoreExceptions())
                && omsAlarmProperties.getIgnoreExceptions().contains(exception.getClass().getCanonicalName());
    }
    /**
     * 判断是否为的忽略告警的预料之中的异常
     *
     * @param exception 发生的异常
     * @return true忽略告警，false告警
     */
    private boolean ignoreExpectedBusinessException(Exception exception) {
        return exception instanceof ExpectedBusinessException
                && Objects.nonNull(omsAlarmProperties.getIgnoreExpectedBusinessException())
                && omsAlarmProperties.getIgnoreExpectedBusinessException();
    }
}
